
package com.platform.modules.app.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.platform.annotation.IgnoreAuth;
import com.platform.annotation.LoginUser;
import com.platform.common.exception.BusinessException;
import com.platform.common.utils.DateUtils;
import com.platform.common.utils.RestResponse;
import com.platform.common.utils.StringUtils;
import com.platform.modules.mall.entity.*;
import com.platform.modules.mall.entity.vo.WxCouponUseRecordVo;
import com.platform.modules.mall.service.MallCartService;
import com.platform.modules.mall.service.MallUserCouponService;
import com.platform.modules.mall.utils.RsaUtil;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author
 */
@Slf4j
@RestController
@RequestMapping("/app/coupon")
@Api(tags = "AppCouponController|优惠券接口")
public class AppCouponController extends AppBaseController {
    @Autowired
    MallUserCouponService userCouponService;

    @Autowired
    MallCartService cartService;

    /**
     * 获取券对应的商品
     *
     * @param //ids
     * @return
     */
//    private List<MallCouponGoodsEntity> getCouponGoods(List<String> ids) {
//        if (ids != null && ids.size() != 0) {
//            return cgService.list(new QueryWrapper<MallCouponGoodsEntity>().in("COUPON_ID", ids));
//        }
//        return null;
//    }

    @GetMapping("/getUseableCoupon")
    @ApiOperation(value = "获取可用的优惠券", notes = "获取可用的优惠券")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "用户token", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "overdue", value = "0可用，1不可用", required = true, dataType = "string"),
    })
    public RestResponse getUseableCoupon(@LoginUser MallUserEntity loginUser, @RequestParam Map<String, Object> params) {
        //根据overdue进行转换 0 = false 可用 1 = true不可用
        boolean tag = params.get("overdue") == null ? false : (Integer.parseInt((String) params.get("overdue"))) == 0 ? false : true;
        //指定用户
        params.put("userId", loginUser.getId());
        if (!tag) {
            //未使用的
            params.put("status", 0);
            //已经开始的
            params.put("hasStarted", 1);
        }
        //只查询未过期的
        params.put("overdue", 0);

        //获取用户所有(初步过滤后)的券
        List<MallUserCouponEntity> listAll = userCouponService.selectAll(params);
        if (listAll == null || listAll.size() == 0) {
            return RestResponse.error("无可用优惠券，赶快去领取呀");
        }

        //获取购物车内商品与对应的价格
        List<Map<String, Object>> cartList = cartService.listMaps(new QueryWrapper<MallCartEntity>()
                .select("GOODS_ID", "RETAIL_PRICE", "number")
                .eq("USER_ID", loginUser.getId())
                .eq("CHECKED", 1)
        );
        if (cartList == null || cartList.size() == 0) {
            return RestResponse.error("请先选购商品");
        }

        //获取购物车总金额
        BigDecimal sum = BigDecimal.valueOf(cartList.stream().mapToDouble(item -> ((((BigDecimal) item.get("RETAIL_PRICE")).multiply(BigDecimal.valueOf((int) item.get("number")))).doubleValue())).sum());
        //指定商品的卡券ID
        List<String> ids = listAll.stream().filter(x -> x.getLimitType() == 1).map(x -> x.getCouponId()).collect(Collectors.toList());
//        List<MallCouponGoodsEntity> cgList = getCouponGoods(ids);
        //过滤 并 按前端所需数据格式进行格式化
        List<Map<String, Object>> list = listAll.stream().filter(coupon -> {
            //已使用的券
            if (coupon.getStatus() == 1) {
                coupon.setExplain("已使用");
                return tag;
            }
            //未开始
            if (DateUtils.compareDate(coupon.getBeginTime(), LocalDate.now()) > 0) {
                coupon.setExplain("未到使用时间");
                return tag;
            }
            //全局券
            if (coupon.getLimitType() == 0) {
                if (sum.compareTo(coupon.getMinPrice()) >= 0) {
                    return !tag;
                }
                if (tag) {
                    coupon.setExplain(String.format("说明：不满足最低使用额度【差：%s￥】", sum.subtract(coupon.getMinPrice()).abs()));
                }
                return tag;
            }
            //指定商品的券
//            if (coupon.getLimitType() == 1 && cgList != null && cgList.size() > 0) {
//                List<String> gIds = cgList.stream().filter(x -> x.getCouponId().equals(coupon.getCouponId())).map(x -> x.getGoodsId()).collect(Collectors.toList());
//                BigDecimal totalMoney = BigDecimal.valueOf(0);
//                for (Map<String, Object> item : cartList) {
//                    if (gIds.contains(item.get("GOODS_ID"))) {
//                        totalMoney = totalMoney.add(((BigDecimal) item.get("RETAIL_PRICE")).multiply(BigDecimal.valueOf((int) item.get("number"))));
//                    }
//                }
//                if (totalMoney.compareTo(coupon.getMinPrice()) >= 0) {
//                    return !tag;
//                } else {
//                    if (tag) {
//                        if (totalMoney.compareTo(BigDecimal.valueOf(0)) <= 0) {
//                            coupon.setExplain("说明：指定商品可用");
//                        } else {
//                            coupon.setExplain(String.format("说明：不满足最低使用额度【差：%s￥】", totalMoney.subtract(coupon.getMinPrice()).abs()));
//                        }
//                    }
//                    return tag;
//                }
//            }
            return false;
        }).map(x -> {
            Map<String, Object> result = new HashMap<>();
            result.put("id", x.getId());
            result.put("couponId", x.getCouponId());
            result.put("name", x.getTitle());
            result.put("condition", x.getMinPrice().doubleValue() <= 0 ? "无门槛" : String.format("满%s可用", x.getMinPrice()));
            result.put("startAt", x.getBeginTime().getTime() / 1000);
            result.put("endAt", x.getEndTime().getTime() / 1000);
            result.put("description", tag ? "" : x.getExplain()); //描述信息，优惠券可用时展示
            result.put("reason", tag ? x.getExplain() : "");    //不可用原因，优惠券不可用时展示
            result.put("value", x.getSubPrice().multiply(BigDecimal.valueOf(100))); //折扣券优惠金额，单位分
            result.put("valueDesc", x.getSubPrice());//折扣券优惠金额文案
            result.put("unitDesc", x.getCouponType() == 1 ? "元" : "折");  // 单位文案
            //result.put("customValidPeriod","有效时间（需替换）"); //自定义有效时间文案
            return result;
        }).collect(Collectors.toList());

        if (listAll.size() == 0) {
            return RestResponse.error("无可用优惠券，快去领取吧");
        }
        return RestResponse.success().put("data", list);
    }

    /**
     * 用户优惠券列表
     */
    @GetMapping("/list")
    @ApiOperation(value = "用户优惠券列表", notes = "用户优惠券列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "用户token", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "overdue", value = "是否过期 1 过期  0未过期", example = "1", dataType = "int")
    })
    public RestResponse list(@LoginUser MallUserEntity loginUser,String overdue) {
        String userId = loginUser.getId();
        if (StringUtils.isBlank(userId)) {
            throw new BusinessException("用户为空!");
        }
        Map<String, Object> params = new HashMap<>(8);
        params.put("userId", userId);
        //用于判断是否过期
        if (overdue != null) {
            if ("1".equals(overdue.trim())) {
                params.put("isOverdue", overdue);
                //返回记录条数
                params.put("topLimit", 10);
            } else {
                params.put("noOverdue", overdue);
            }
        }
        // 再排序
        List<MallUserCouponEntity> list = userCouponService.queryAll(params).stream()
                .sorted((o1, o2) -> (int) (o2.getAddTime().getTime() - o1.getAddTime().getTime()))
                .sorted(Comparator.comparingInt(x -> x.getStatus()))
                .collect(Collectors.toList());
        return RestResponse.success().put("data", list);
    }

//    @GetMapping("/couponList")
//    @ApiOperation(value = "可领取优惠券", notes = "可领取优惠券")
//    @ApiResponses({
//            @ApiResponse(code = 200, message = "OK", response = MallCouponEntity.class),
//    })
//    public RestResponse couponList(@LoginUser MallUserEntity user) {
//        List<MallCouponEntity> couponEntityList = couponService.list(new QueryWrapper<MallCouponEntity>()
//                .ge("END_GET_TIME", LocalDate.now())
//                .eq("STATUS", 1)
//                .and(x -> x.eq("user_level_id", user.getUserLevelId()).or().eq("user_level_id", "-1"))
//                .orderByDesc("SORT")
//        );
//        Date[] dates = DateUtils.getMonthStartAndEnd(0);
//        //过滤
//        couponEntityList = couponEntityList.stream().map(item -> {
//            if (item.getTotalCount().intValue() == item.getSendCount().intValue()) {
//                item.setNotApplicable("无库存");
//            }
//            if (item.getIsCirculation()) {
//                item.setBeginTime(dates[0]);
//                item.setEndTime(dates[1]);
//            }
//            if (couponService.getUserCouponCount(user.getId(), item, null, true) <= 0) {
//                item.setNotApplicable((item.getIsCirculation() ? "每月" : "") + "限领" + item.getLimitUser() + "张");
//            }
//            return item;
//        }).collect(Collectors.toList());
//
//        return RestResponse.success().put("data", couponEntityList);
//    }

//    @GetMapping("/getCouponUser")
//    @ApiOperation(value = "获取优惠券", notes = "获取优惠券")
//    @ApiImplicitParams({
//            @ApiImplicitParam(paramType = "header", name = "token", value = "用户token", required = true, dataType = "string"),
//            @ApiImplicitParam(paramType = "query", name = "couponId", value = "优惠券ID", example = "1", required = true, dataType = "string")
//    })
//    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
//    public RestResponse getCouponUser(@LoginUser MallUserEntity loginUser, String couponId) {
//        String userId = loginUser.getId();
//        if (StringUtils.isBlank(userId)) {
//            throw new BusinessException("用户为空!");
//        }
////        MallCouponEntity couponEntity = couponService.getById(couponId);
//
//        if (!"-1".equals(couponEntity.getUserLevelId()) && !couponEntity.getUserLevelId().equals(loginUser.getUserLevelId())) {
//            throw new BusinessException("不满足领取等级");
//        }
//        if (couponEntity.getStatus() != 1) {
//            throw new BusinessException("优惠券已失效");
//        }
//        if (DateUtils.compareDate(LocalDate.now(), couponEntity.getEndGetTime()) > 0) {
//            throw new BusinessException("优惠券已失效");
//        }
//        if (DateUtils.compareDate(couponEntity.getBeginGetTime(), LocalDate.now()) > 0) {
//            throw new BusinessException("暂未开放领取");
//        }
//        if (couponEntity.getSendCount() >= couponEntity.getTotalCount()) {
//            throw new BusinessException("优惠券已领完");
//        }
//        //使用 AtomicInteger 进行int的引用类型传递 传入Type  返回用户下次可领取次数
//        AtomicInteger typeNumber = new AtomicInteger(2);
//        userCouponService.save(couponService.sendCoupon(userId, couponEntity, typeNumber));
//        RestResponse result = RestResponse.success();
//        if (couponEntity.getSendCount() == couponEntity.getTotalCount() - 1) {
//            result.put("num", -1);
//        } else {
//            result.put("num", typeNumber.decrementAndGet());
//        }
//        return result;
//    }

    /**
     * 用户优惠券数量
     */
    @GetMapping("/userCount")
    @ApiOperation(value = "用户优惠券数量", notes = "用户优惠券数量")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "用户token", required = true, dataType = "string")
    })
    public RestResponse userCount(@LoginUser MallUserEntity loginUser) {
        String userId = loginUser.getId();
        if (StringUtils.isBlank(userId)) {
            throw new BusinessException("用户为空!");
        }
        return RestResponse.success().put("data", userCouponService.count(new QueryWrapper<MallUserCouponEntity>()
                .eq("USER_ID", loginUser.getId()).eq("status", 0)
        ));
    }


    @Value("${wx.coupon.publickey}")
    private String pubkey;



    /**
     * @startuml
     * actor 用户 as user
     * participant 卡券系统 as kaquan #red
     * participant 微信支付平台 as wxpay
     * participant 核销平台 as hexiao
     * user -> kaquan :获得卡券
     * activate kaquan
     * kaquan -> kaquan :抽奖、购买等
     * alt 获得失败情况
     *  kaquan -> user :返回获得卡券失败结果
     * else 成功情况
     *  kaquan -> user :返回获得卡券成功
     * deactivate kaquan
     *  kaquan -> kaquan:定时任务：发送未成功卡券
     * activate kaquan
     *  kaquan -> wxpay :给用户发送卡券
     * activate wxpay
     *  wxpay -> kaquan :返回发送结果
     * deactivate wxpay
     * deactivate kaquan
     * end
     * user -> wxpay :发起支付，使用卡券
     * activate wxpay
     * alt 使用失败
     *  wxpay -> user :返回支付失败
     * else 使用成功
     *  wxpay -> user :返回支付成功
     *  wxpay --> hexiao :发送卡券支付使用结果
     * deactivate wxpay
     *  hexiao --[#red]> kaquan :根据批次配置，向不同系统发送卡券结果
     * end
     *
     * @enduml
     * 测试异步回调
     * @param entity
     * @return
     */
    @PostMapping("callback")
    @ApiOperation(value = "卡券核销异步回调", notes = "卡券核销异步回调")
    @IgnoreAuth
    public String callback(@RequestBody WxCouponUseRecordVo entity){

        StringBuilder sb =new StringBuilder();
        sb.append(entity.getStockId()).append("|")
                .append(entity.getCouponId()).append("|")
                .append(entity.getConsumeMchid());

        try {
            boolean verify = RsaUtil.verify(sb.toString(), RsaUtil.getPublicKey(pubkey), entity.getSign());
            log.info("----验证结果：{}------",verify);
            //todo 处理卡卷核销情况
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "fail";
    }


}
